//
//  WmcAuthorizationManager.swift
//  YPWatermarkCamera
//
//  Created by 周诗松 on 2022/4/13.
//

import Alamofire
import Foundation
import YPBedrock

// MARK: - [WmcAuthorizationType]

extension WmcAuthorizedManager {
    public enum AuthorizedType {
        /// 网络
        case network
        /// 摄像头
        case camera
        /// 相册
        case photoAlbum
        /// 定位
        case location
        /// 麦克风
        case microphone
        /// 通知
        case notification
        /// 广告标识符
        case idfa

        struct Info {
            var name: String
        }

        var info: Info {
            switch self {
            case .network: return .init(name: "网络")
            case .camera: return .init(name: "摄像头")
            case .photoAlbum: return .init(name: "相册")
            case .location: return .init(name: "定位")
            case .microphone: return .init(name: "麦克风")
            case .notification: return .init(name: "通知")
            case .idfa: return .init(name: "广告标识符")
            }
        }
    }

    /// 授权状态
    enum Status {
        /// 授权访问
        case authorized
        /// 拒绝访问
        case denied
        /// 部分访问
        case limited
        /// 限制访问，用户不能改变客户机的状态,可能由于活跃的限制,如家长控制
        case restricted
        /// 尚未选择，表明用户尚未选择关于客户端是否可以访问硬件
        case notDetermined
        /// 未知
        case unknow

        struct Info {
            /// 描述
            var description: String
            /// 是否可用
            var isAvailable: Bool
        }

        var info: Info {
            switch self {
            case .authorized:
                return .init(description: "授权访问",
                             isAvailable: true)
            case .denied:
                return .init(description: "拒绝访问",
                             isAvailable: false)
            case .limited:
                return .init(description: "部分访问",
                             isAvailable: true)
            case .restricted:
                return .init(description: "限制访问，用户不能改变客户机的状态，可能由于活跃的限制,如家长控制",
                             isAvailable: true)
            case .notDetermined:
                return .init(description: "尚未选择，表明用户尚未选择关于客户端是否可以访问硬件",
                             isAvailable: false)
            case .unknow:
                return .init(description: "授权访问",
                             isAvailable: false)
            }
        }
    }
}

// MARK: - [WmcAuthorizedManager]

class WmcAuthorizedManager: NSObject {
    // Internal

    /// 单例实例化
    static let shared: WmcAuthorizedManager = {
        let manager = WmcAuthorizedManager()
        return manager
    }()

    /// 定位状态，私有
    /// 用于承接代理
    @available(iOS, introduced: 6, deprecated: 14, message: "后期需要撤掉这个方法")

    /// 获取权限
    /// - Parameters:
    ///   - type: 权限类型
    ///   - isHint: 是否需要弹窗提示，默认需要
    static func showPrivacyAlert(type: AuthorizedType, isHint: Bool = true, msg: String? = nil, height: CGFloat? = nil, otherConfig: ((WmcAlertView) -> Void)? = nil) {
        if !isHint {
            openSetting()
            return
        }
        let alert = WmcAlertView()
        alert.title = "提示"
        if let msg = msg,
           !msg.isEmpty {
            alert.msg = msg
        } else{
            alert.msg = "没有\(type.info.name)权限"
        }
        alert.style = .custom(confirmTitle: "去开启", cancelTitle: "取消")
        alert.confirmBlock = {
            openSetting()
        }
        otherConfig?(alert)
        if let height = height {
            alert.show(height: height)
        } else {
            alert.show()
        }
    }
    

    func config() {}

    // Private

    /// 定位管理，私有
    /// 用于承接代理
    private lazy var locationManager: CLLocationManager = {
        let manager = CLLocationManager()
        manager.delegate = self
        return manager
    }()

    /// 定位回调，私有
    /// 用于承接代理
    private var locationDelegateSaveRequestBlock: YPBlock.OneParam<Status>?
}

// MARK: - 网络权限

import CoreTelephony

extension WmcAuthorizedManager {
    /// 获取蜂窝网络权限状态
    static func ethernetNetwork(_ resultBlock: @escaping YPBlock.OneParam<Status>) {
        var status: Status = .unknow
        let state = CTCellularData().restrictedState
        switch state {
        case .restrictedStateUnknown: status = .unknow
        case .restricted: status = .authorized
        case .notRestricted: status = .notDetermined
        @unknown default: status = .unknow
        }
        log("获取蜂窝网络权限：\(status)")
        resultBlock(status)
    }

    /// 获取网络权限状态
    static func network(_ resultBlock: @escaping YPBlock.OneParam<Status>) {
        guard let netManager = NetworkReachabilityManager() else {
            resultBlock(.unknow)
            return
        }
        var status: Status = .unknow
        switch netManager.status {
        case .unknown: status = .unknow
        case .notReachable: status = .denied
        case .reachable: status = .authorized
        }
        log("获取网络权限：\(status)")
        resultBlock(status)
    }
}

// MARK: - 摄像头权限

import KeychainAccess
import Photos

extension WmcAuthorizedManager {
    /// 获取摄像头权限状态
    static func camera() -> Status {
        var status: Status = .unknow
        let authStatus = AVCaptureDevice.authorizationStatus(for: .video)
        switch authStatus {
        case .authorized: status = .authorized
        case .restricted: status = .restricted
        case .denied: status = .denied
        case .notDetermined: status = .notDetermined
        @unknown default: status = .unknow
        }
        log("获取摄像头权限：\(status)")
        return status
    }

    /// 请求摄像头权限
    static func cameraRequest(_ resultBlock: YPBlock.OneParam<Status>? = nil) {
        AVCaptureDevice.requestAccess(for: .video) { bool in
            YPGCD.Main {
                let status: Status = bool ? .authorized : .denied
                log("请求摄像头权限：\(status)")
                resultBlock?(status)
            }
        }
    }
    
    /// 弹出相机权限弹窗
    static func showCameraPermissionAlert() {
        showPrivacyAlert(type: .camera, msg: "开启相机权限，即可正常拍摄")
    }
}

// MARK: - 麦克风权限

import AVFoundation

extension WmcAuthorizedManager {
    /// 获取麦克风权限状态
    static func microphone() -> Status {
        let authStatus = AVCaptureDevice.authorizationStatus(for: .audio)
        var status: Status = .unknow
        switch authStatus {
        case .notDetermined: status = .notDetermined
        case .restricted: status = .restricted
        case .denied: status = .denied
        case .authorized: status = .authorized
        @unknown default: status = .unknow
        }
        log("获取麦克风权限：\(status)")
        return status
    }

    /// 请求麦克风权限
    static func microphoneRequest(_ resultBlock: YPBlock.OneParam<Status>? = nil) {
        AVCaptureDevice.requestAccess(for: .audio) { bool in
            YPGCD.Main {
                let status: Status = bool ? .authorized : .denied
                log("请求麦克风权限：\(status)")
                resultBlock?(status)
            }
        }
    }
}

// MARK: - 相册权限

extension WmcAuthorizedManager {
    /// 获取相册权限状态
    static func photoAlbum() -> Status {
        var status: Status = .unknow
        if #available(iOS 14, *) {
            let authStatus = PHPhotoLibrary.authorizationStatus(for: .readWrite)
            status = judgePhotoAlbumStatus(authStatus)
        } else {
            let authStatus = PHPhotoLibrary.authorizationStatus()
            status = judgePhotoAlbumStatus(authStatus)
        }
        log("获取相册权限：\(status)")
        return status
    }

    /// 请求相册权限
    static func photoAlbumRequest(_ resultBlock: YPBlock.OneParam<Status>? = nil) {
        if #available(iOS 14, *) {
            PHPhotoLibrary.requestAuthorization(for: .readWrite) { (authStatus) in
                let status = judgePhotoAlbumStatus(authStatus)
                YPGCD.Main {
                    log("请求相册权限：\(status)")
                    resultBlock?(status)
                }
            }
        } else {
            PHPhotoLibrary.requestAuthorization { authStatus in
                let status = judgePhotoAlbumStatus(authStatus)
                YPGCD.Main {
                    log("请求相册权限：\(status)")
                    resultBlock?(status)
                }
            }
        }
    }
    /// 相册权限未授权处理(包含Not Determine)
    static func handleAlbumAuthorizationNotAvailable() {
        if Thread.isMainThread {
            _handleAlbumAuthorizationNotAvailable()
        } else {
            YPGCD.Main {
                _handleAlbumAuthorizationNotAvailable()
            }
        }
    }
    
    /// 相册权限未授权处理(包含Not Determine)
    private static func _handleAlbumAuthorizationNotAvailable() {
        let photoAlbumStatus = WmcAuthorizedManager.photoAlbum()
        if photoAlbumStatus == .notDetermined {
            photoAlbumRequest { status in
                if status.info.isAvailable { // 有权限
                    WmcPrint("同意相册权限")
                } else { // 无权限
                    WmcPrint("拒绝相册权限")
                }
            }
        } else {
            var msg: String = "授权相册权限，用于将您拍摄的照片保存至手机相册或选择本地照片进行编辑"
            if !YPWmcManager.shared.isIndependentPage { // 非独立包
                // TODO: 应通过代理抛出
                if let _msg = YPWmcManager.shared.delegate.authorityDelegate?.photoAlbumAuthorityDescription(),
                  !_msg.isEmpty { // 如果宿主包返回了权限描述,使用返回的描述
                    msg = _msg
                }
//                else { // 如果宿主包没有返回(应该由鱼泡返回,暂时先这样处理)
//                    msg = "访问相册用于预览本地图片/视频、保存拍摄的图片/视频到本地相册、上传头像选择、招工/简历相关信息展示所需的照片。若您拒绝授权，将影响上述功能的使用，但不会影响求职招聘基本功能使用。"
//                }
            }
            showPrivacyAlert(type: .photoAlbum, msg: msg, height: 200.0)
        }
    }
    

    private static func judgePhotoAlbumStatus(_ authorizationStatus: PHAuthorizationStatus) -> Status {
        var status: Status = .unknow
        switch authorizationStatus {
        case .authorized: status = .authorized
        case .limited: status = .limited
        case .restricted: status = .restricted
        case .denied: status = .denied
        case .notDetermined: status = .notDetermined
        @unknown default: status = .unknow
        }
        return status
    }
}

// MARK: - 定位权限

extension WmcAuthorizedManager {
    /// 获取定位权限状态同步
    static func location() -> Status {
        var status: Status = .unknow
        // 手机的定位权限
//        if !CLLocationManager.locationServicesEnabled() {
//            status = .denied
//        }
        // 应用的定位权限
        let authStatus = CLLocationManager.authorizationStatus()
        switch authStatus {
        case .authorizedAlways: status = .authorized
        case .authorizedWhenInUse: status = .authorized
        case .denied: status = .denied
        case .notDetermined: status = .notDetermined
        case .restricted: status = .restricted
        @unknown default: status = .unknow
        }
        log("获取定位权限：\(status)")
        return status
    }

    /// 请求定位权限
    static func locationRequest(_ resultBlock: YPBlock.OneParam<Status>? = nil) {
        let lo = location()
        if location() == .denied {
            resultBlock?(.denied)
        }else{
            WmcAuthorizedManager.shared.locationDelegateSaveRequestBlock = { status in
                guard status != .notDetermined else { return } // 等待用户选择
                log("请求定位权限：\(status)")
                resultBlock?(status)
            }
            // 发起请求
            WmcAuthorizedManager.shared.locationManager.requestWhenInUseAuthorization()
        }
    }
}

// MARK: - CLLocationManagerDelegate

extension WmcAuthorizedManager: CLLocationManagerDelegate {
    // iOS14以下支持
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        var result: Status = .unknow
        switch status {
        case .authorizedAlways: result = .authorized
        case .authorizedWhenInUse: result = .authorized
        case .denied: result = .denied
        case .notDetermined: result = .notDetermined
        case .restricted: result = .restricted
        @unknown default: result = .unknow
        }
        locationDelegateSaveRequestBlock?(result)
    }

    // iOS14支持
    func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
        var result: Status = .unknow
        if #available(iOS 14.0, *) {
            switch manager.authorizationStatus {
            case .authorizedAlways: result = .authorized
            case .authorizedWhenInUse: result = .authorized
            case .denied: result = .denied
            case .notDetermined: result = .notDetermined
            case .restricted: result = .restricted
            @unknown default: result = .unknow
            }
            locationDelegateSaveRequestBlock?(result)
        } else {
            locationDelegateSaveRequestBlock?(.unknow)
        }
    }
}

// MARK: - 通知权限

extension WmcAuthorizedManager {
    /// 获取通知权限状态
    static func notification(_ resultBlock: @escaping YPBlock.OneParam<Status>) {
        var status: Status = .unknow
        UNUserNotificationCenter.current().getNotificationSettings { (settings) in
            switch settings.authorizationStatus {
            case .notDetermined: status = .notDetermined
            case .denied: status = .denied
            case .authorized: status = .authorized
            case .provisional: status = .restricted
            case .ephemeral: status = .restricted
            @unknown default: status = .unknow
            }
        }
        log("获取通知权限：\(status)")
        resultBlock(status)
    }

    /// 通知请求权限
    static func notificationRequest(_ resultBlock: YPBlock.OneParam<Status>? = nil) {
        let center = UNUserNotificationCenter.current()
        center.requestAuthorization { bool, error in
            if let error = error {
                log("请求通知权限失败！error：\(error)")
            } else {
                let status: Status = bool ? .authorized : .denied
                log("请求通知权限：\(status)")
                resultBlock?(status)
            }
        }
    }
}

// MARK: - 广告标识符权限

import AdSupport
import AppTrackingTransparency

extension WmcAuthorizedManager {
    /// 获取广告标识符权限状态
    static func idfa() -> Status {
        var status: Status = .unknow
        if #available(iOS 14, *) {
            let trackingStatus = ATTrackingManager.trackingAuthorizationStatus
            status = judgeIdfaStatus(trackingStatus)
        } else { // iOS13及之前版本，继续用以前的方式
            if ASIdentifierManager.shared().isAdvertisingTrackingEnabled {
                status = .authorized
            } else {
                status = .denied
            }
        }
        log("获取广告标识符Idfa权限：\(status)")
        return status
    }

    /// IDFA请求权限
    static func idfaRequest(_ resultBlock: YPBlock.OneParam<Status>? = nil) {
        var status: Status = .unknow
        if #available(iOS 14, *) {
            ATTrackingManager.requestTrackingAuthorization { (authStatus) in
                status = judgeIdfaStatus(authStatus)
            }
        } else { // iOS13及之前版本，继续用以前的方式
            if ASIdentifierManager.shared().isAdvertisingTrackingEnabled {
                status = .authorized
            } else {
                status = .denied
            }
        }
        log("请求广告标识符Idfa权限：\(status)")
        resultBlock?(status)
    }

    @available(iOS 14, *)
    private static func judgeIdfaStatus(_ authorizationStatus: ATTrackingManager.AuthorizationStatus) -> Status {
        var status: Status = .unknow
        switch authorizationStatus {
        case .authorized: status = .authorized
        case .restricted: status = .restricted
        case .denied: status = .denied
        case .notDetermined: status = .notDetermined
        @unknown default: status = .unknow
        }
        return status
    }
}

// MARK: - 其他

extension WmcAuthorizedManager {
    /// 日志系统
    static func log(_ log: String) {
        WmcLogManager.DebugLog(type: .permissions, log: log)
    }
    /// 跳转设置页面
    static func openSetting() {
        guard let url = URL(string: UIApplication.openSettingsURLString) else {
            return
        }
        if #available(iOS 10.0, *) {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
        } else {
            UIApplication.shared.openURL(url)
        }
    }
}
